package apps.sim.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

import apps.sim.core.IHandler.Util;
import apps.sim.util.LoadConfig;
import apps.sim.util.thread.GenericTaskExecutor;
import apps.sim.util.thread.ServiceExecutor;
import apps.sim.util.thread.ServiceProxy;
import apps.sim.util.thread.TaskContainer;

import com.sun.net.httpserver.HttpExchange;

public class HttpLoadTestHandler extends HttpBaseHandler {
	private List<Future<ServiceProxy>> execute = null;
	private CountDownLatch latch = null;
	private int originalSize = 0;

	@Override
	protected void execute(HttpExchange exchange) throws Exception {
		final Map<String, String> getParams = extractParams(exchange.getRequestURI());
		final String status = getParams.get("status");
		if (status == null || "".equals(status)) {
			startExecution(exchange, getParams);
		} else {
			readData(exchange);
		}
	}

	private void readData(HttpExchange exchange) throws IOException {
		if (latch != null) {
			final long count = latch.getCount();
			if (count == 0) {
				doReports(exchange);
			} else {
				doPartialReport(exchange, count);
			}
		} else {
			successResponse(exchange, "Pending..");
		}
	}

	private void doPartialReport(HttpExchange exchange, long count) throws IOException {
		successResponse(exchange, "Tasks: " + originalSize + ". Pending: " + count);
	}

	private void doReports(HttpExchange exchange) throws IOException {
		successResponse(exchange, "Finished");
	}

	private void startExecution(HttpExchange exchange, final Map<String, String> getParams) throws IOException, UnsupportedEncodingException, Exception {
		final byte[] readDataAsByte = Util.readDataAsString(exchange.getRequestBody());
		final String x = new String(readDataAsByte);
		final String decode = URLDecoder.decode(x, "UTF-8");
		final String[] split = decode.split("&&&");
		final Map<String, String> params = getParams;
		for (String string : split) {
			final int indexOf = string.indexOf("=");
			if (indexOf != -1) {
				params.put(string.substring(0, indexOf), string.substring(indexOf + 1));
			}
		}
		final String target = params.get("target");
		final String headers = params.get("headers");
		final String operation = params.get("operation");
		final String user = params.get("user");
		final String password = params.get("password");
		final String threadCount = params.get("threadcount");
		final String requestCount = params.get("requestCount");
		final String request = params.get("request");
		final LoadConfig config = new LoadConfig(target, headers, operation, user, password, threadCount, requestCount, request);
		config.validate();
		final GenericTaskExecutor executorService = new GenericTaskExecutor("Test-executor", config.getThreadCount(), config.getThreadCount());
		final ServiceProxy serviceProxy = new ServiceProxy(target, operation, headers, user, password, request);
		final TaskContainer<ServiceProxy> container = new TaskContainer<ServiceProxy>();
		for (int index = 0; index < config.getRequestCount(); index++) {
			container.add(new ServiceExecutor(serviceProxy));
		}
		originalSize = container.taskCount();
		latch = new CountDownLatch(container.taskCount());
		execute = executorService.execute(container, 1000L, latch, true, true);
		successResponse(exchange, "Execution Started");
	}
}
